package com.xyht.medicine_management_system.modules.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ExceptionCast;
import com.xyht.medicine_management_system.common.commonReturn.ResponseResult;
import com.xyht.medicine_management_system.common.util.TimeUtil;
import com.xyht.medicine_management_system.modules.addresses.entity.MmsAddresses;
import com.xyht.medicine_management_system.modules.addresses.mapper.MmsAddressesMapper;
import com.xyht.medicine_management_system.modules.consumptionPoint.entity.MmsConsumptionPointRecord;
import com.xyht.medicine_management_system.modules.consumptionPoint.mapper.MmsConsumptionPointRecordMapper;
import com.xyht.medicine_management_system.modules.coupon.constant.UserCouponRelationConstant;
import com.xyht.medicine_management_system.modules.coupon.entity.MmsUserCouponRelation;
import com.xyht.medicine_management_system.modules.coupon.entity.resp.MmsCouponResp;
import com.xyht.medicine_management_system.modules.coupon.entity.resp.MmsUserCouponRelationResp;
import com.xyht.medicine_management_system.modules.coupon.mapper.MmsUserCouponRelationMapper;
import com.xyht.medicine_management_system.modules.coupon.util.CouponUtil;
import com.xyht.medicine_management_system.modules.medicine.constant.MedicineIsOnConstant;
import com.xyht.medicine_management_system.modules.medicine.entity.MmsMedicine;
import com.xyht.medicine_management_system.modules.medicine.mapper.MmsMedicineMapper;
import com.xyht.medicine_management_system.modules.medicine.util.MedicineUtil;
import com.xyht.medicine_management_system.modules.order.constant.OrderConstant;
import com.xyht.medicine_management_system.modules.order.constant.OrderScheduleConstant;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrder;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrderRefund;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrderSchedule;
import com.xyht.medicine_management_system.modules.order.entity.req.CheckoutReq;
import com.xyht.medicine_management_system.modules.order.entity.req.MmsOrderReq;
import com.xyht.medicine_management_system.modules.order.entity.req.SimpleMedicineReq;
import com.xyht.medicine_management_system.modules.order.entity.req.SubmitOrderReq;
import com.xyht.medicine_management_system.modules.order.entity.resp.CheckoutResp;
import com.xyht.medicine_management_system.modules.order.entity.resp.MmsOrderRefundResp;
import com.xyht.medicine_management_system.modules.order.entity.resp.MmsOrderResp;
import com.xyht.medicine_management_system.modules.order.entity.resp.OrderMedicineInfoResp;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderMapper;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderMedicineInfoMapper;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderRefundMapper;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderScheduleMapper;
import com.xyht.medicine_management_system.modules.order.service.MmsOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.medicine_management_system.modules.order.util.OrderScheduleUtil;
import com.xyht.medicine_management_system.modules.order.util.OrderUtil;
import com.xyht.medicine_management_system.modules.payment.util.PaymentUtil;
import com.xyht.medicine_management_system.modules.payment.wxpay.entity.PrepayPaymentReq;
import com.xyht.medicine_management_system.modules.stock.util.MedicineStockUtil;
import com.xyht.medicine_management_system.modules.user.entity.MmsUser;
import com.xyht.medicine_management_system.modules.user.entity.resp.MmsUserResp;
import com.xyht.medicine_management_system.modules.user.mapper.MmsUserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyht.medicine_management_system.common.util.ParamCheckUtil.isNullOrEmpty;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-12-14
 */
@Service
public class MmsOrderServiceImpl extends ServiceImpl<MmsOrderMapper, MmsOrder> implements MmsOrderService {
    @Resource
    private MmsMedicineMapper mmsMedicineMapper;
    @Resource
    private MedicineUtil medicineUtil;
    @Resource
    private MedicineStockUtil medicineStockUtil;
    @Resource
    private CouponUtil couponUtil;
    @Resource
    private OrderUtil orderUtil;
    @Resource
    private MmsAddressesMapper mmsAddressesMapper;
    @Resource
    private MmsUserCouponRelationMapper mmsUserCouponRelationMapper;
    @Resource
    private OrderScheduleUtil orderScheduleUtil;
    @Resource
    private MmsOrderScheduleMapper mmsOrderScheduleMapper;
    @Resource
    private MmsOrderRefundMapper mmsOrderRefundMapper;
    @Resource
    private MmsOrderMedicineInfoMapper mmsOrderMedicineInfoMapper;
    @Resource
    private PaymentUtil paymentUtil;
    @Resource
    private MmsUserMapper mmsUserMapper;
    @Resource
    private MmsConsumptionPointRecordMapper mmsConsumptionPointRecordMapper;

    @Override
    public ResponseResult calculateMoney(CheckoutReq checkoutReq, String userId) {
        if (checkoutReq.getSimpleMedicineList().isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 药品总价
        BigDecimal totalPrice = new BigDecimal(0);
        for (SimpleMedicineReq simpleMedicineReq : checkoutReq.getSimpleMedicineList()) {
            // 药品id, 数量必填
            if (isNullOrEmpty(simpleMedicineReq.getMedicineId(), simpleMedicineReq.getMedicineNum())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            // 数量必须大于0
            if (simpleMedicineReq.getMedicineNum() <= 0) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            MmsMedicine medicine = mmsMedicineMapper.selectById(simpleMedicineReq.getMedicineId());
            // 校验药品是否存在
            if (isNullOrEmpty(medicine)) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_NOT_EXIST);
            }

            // 计算当前药品价格: 药品价格 = 药品真实价格 * 药品数量
            BigDecimal medicinePrice = medicineUtil.getRealPrice(medicine.getId()).multiply(BigDecimal.valueOf(simpleMedicineReq.getMedicineNum()));
            // 计算总价
            totalPrice = totalPrice.add(medicinePrice);
        }

        // 构造回传数据
        CheckoutResp checkoutResp = new CheckoutResp();
        BeanUtils.copyProperties(checkoutReq, checkoutResp);

        // 获取当前用户可用优惠券
        List<MmsUserCouponRelationResp> validCouponList = couponUtil.getValidCouponList(userId, totalPrice);
        if (!validCouponList.isEmpty()) {
            MmsCouponResp couponInfo = new MmsCouponResp();
            // 使用用户指定的优惠券
            if (!isNullOrEmpty(checkoutReq.getUserCouponId())) {
                List<MmsUserCouponRelationResp> couponInfoList = validCouponList.stream().filter(UserCoupon -> UserCoupon.getId().equals(checkoutReq.getUserCouponId())).collect(Collectors.toList());
                if (!couponInfoList.isEmpty()) {
                    couponInfo = couponInfoList.get(0).getCouponInfo();
                }
            }

            // 默认使用金额最高的优惠券
            if (isNullOrEmpty(couponInfo.getId())) {
                couponInfo = validCouponList.get(0).getCouponInfo();
            }

            // 设置 优惠金额
            BigDecimal discountAmount = couponInfo.getDiscountAmount();

            // 校验 总价是否小于优惠价
            if (totalPrice.compareTo(discountAmount) < 0) {
                discountAmount = totalPrice; // 优惠金额设置为当前总价
                totalPrice = BigDecimal.valueOf(0); // 总价设为0
            } else {
                // 计算总价: 总价 = 总价 - 优惠金额
                totalPrice = totalPrice.subtract(discountAmount);
            }

            couponInfo.setDiscountAmount(discountAmount); // 使用的该优惠券设置优惠金额

            checkoutResp.setUserCouponId(couponInfo.getId()); // 设置用户使用的优惠券关系id
            checkoutResp.setDiscountAmount(discountAmount); // 设置优惠金额
        }

        checkoutResp.setValidCouponList(validCouponList); // 可用优惠券
        checkoutResp.setTotalPrice(totalPrice); // 合计

        return CommonResult.success(checkoutResp);
    }

    @Override
    public ResponseResult checkout(CheckoutReq checkoutReq, String userId) {
        if (checkoutReq.getSimpleMedicineList().isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 药品总价
        BigDecimal totalPrice = new BigDecimal(0);
        for (SimpleMedicineReq simpleMedicineReq : checkoutReq.getSimpleMedicineList()) {
            // 药品id, 数量必填
            if (isNullOrEmpty(simpleMedicineReq.getMedicineId(), simpleMedicineReq.getMedicineNum())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            // 数量必须大于0
            if (simpleMedicineReq.getMedicineNum() <= 0) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            MmsMedicine medicine = mmsMedicineMapper.selectById(simpleMedicineReq.getMedicineId());
            // 校验药品是否存在
            if (isNullOrEmpty(medicine)) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_NOT_EXIST);
            }
            // 校验是否上架
            if (medicine.getIsOn() != MedicineIsOnConstant.MEDICINE_IS_ON) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_IS_OFF);
            }
            // 校验药品库存
            if (medicineStockUtil.getMedicineStock(medicine.getId()) < simpleMedicineReq.getMedicineNum()) {
                return CommonResult.failed(CommonCodeEnum.ORDER_MEDICINE_OUT_OF_STOCK);
            }

            // 计算当前药品价格: 药品价格 = 药品真实价格 * 药品数量
            BigDecimal medicinePrice = medicineUtil.getRealPrice(medicine.getId()).multiply(BigDecimal.valueOf(simpleMedicineReq.getMedicineNum()));
            // 计算总价
            totalPrice = totalPrice.add(medicinePrice);
        }

        // 构造回传数据
        CheckoutResp checkoutResp = new CheckoutResp();
        BeanUtils.copyProperties(checkoutReq, checkoutResp);

        // 获取当前用户可用优惠券
        List<MmsUserCouponRelationResp> validCouponList = couponUtil.getValidCouponList(userId, totalPrice);
        if (!validCouponList.isEmpty() && !isNullOrEmpty(checkoutReq.getUserCouponId())) {
            // 使用用户选择的优惠券
            List<MmsUserCouponRelationResp> couponInfoList = validCouponList.stream().filter(UserCoupon -> UserCoupon.getId().equals(checkoutReq.getUserCouponId())).collect(Collectors.toList());
            if (couponInfoList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.ORDER_COUPON_NOT_AVAILABLE);
            }
            MmsCouponResp couponInfo = couponInfoList.get(0).getCouponInfo();

            // 设置 优惠金额
            BigDecimal discountAmount = couponInfo.getDiscountAmount();

            // 校验 总价是否小于优惠价
            if (totalPrice.compareTo(discountAmount) < 0) {
                discountAmount = totalPrice; // 优惠金额设置为当前总价
                totalPrice = BigDecimal.valueOf(0); // 总价设为0
            } else {
                // 计算总价: 总价 = 总价 - 优惠金额
                totalPrice = totalPrice.subtract(discountAmount);
            }

            couponInfo.setDiscountAmount(discountAmount); // 使用的该优惠券设置优惠金额

            checkoutResp.setUserCouponId(couponInfo.getId()); // 设置用户使用的优惠券关系id
            checkoutResp.setDiscountAmount(discountAmount); // 设置优惠金额
        }

        checkoutResp.setValidCouponList(validCouponList); // 可用优惠券
        checkoutResp.setTotalPrice(totalPrice); // 合计

        return CommonResult.success(checkoutResp);
    }

    @Override
    @Transactional
    public ResponseResult submitOrder(SubmitOrderReq orderReq, String userId) {
        if (isNullOrEmpty(orderReq.getSimpleMedicineList(), orderReq.getAddressId(), orderReq.getPaymentMethod())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        // 校验支付方式
        if (!orderReq.getPaymentMethod().equals(OrderConstant.ORDER_PAYMENT_METHOD_WXPAY) &&
                !orderReq.getPaymentMethod().equals(OrderConstant.ORDER_PAYMENT_METHOD_ALIPAY)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        // 校验当前用户地址是否存在
        List<MmsAddresses> addressList = mmsAddressesMapper.selectList(new LambdaQueryWrapper<MmsAddresses>()
                .eq(MmsAddresses::getId, orderReq.getAddressId())
                .eq(MmsAddresses::getUserId, userId));
        if (addressList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.ADDRESS_NOT_EXIST);
        }

        // 校验药品是否可售卖 并 计算总价
        BigDecimal totalPrice = new BigDecimal(0);
        List<OrderMedicineInfoResp> medicineInfoRespList = new ArrayList<>();
        // 收集商品描述以供预支付使用
        List<String> orderDescription = new ArrayList<>();
        for (SimpleMedicineReq simpleMedicineReq : orderReq.getSimpleMedicineList()) {
            // 药品id, 数量 必填
            if (isNullOrEmpty(simpleMedicineReq.getMedicineId(), simpleMedicineReq.getMedicineNum())) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            // 数量必须大于0
            if (simpleMedicineReq.getMedicineNum() <= 0) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }

            MmsMedicine medicine = mmsMedicineMapper.selectById(simpleMedicineReq.getMedicineId());
            // 校验药品是否存在
            if (isNullOrEmpty(medicine)) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_NOT_EXIST);
            }
            // 校验是否上架
            if (medicine.getIsOn() != MedicineIsOnConstant.MEDICINE_IS_ON) {
                return CommonResult.failed(CommonCodeEnum.MEDICINE_IS_OFF);
            }
            // 校验药品库存并减少库存
            if (medicineStockUtil.getMedicineStock(medicine.getId()) < simpleMedicineReq.getMedicineNum()) {
                return CommonResult.failed(CommonCodeEnum.ORDER_MEDICINE_OUT_OF_STOCK);
            }
            boolean reduceSuccess = medicineStockUtil.reduceMedicineStock(medicine.getId(), simpleMedicineReq.getMedicineNum(), userId);
            if (!reduceSuccess) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_MEDICINE_REDUCE_STOCK_FAIL));
            }

            // 计算当前药品价格: 药品价格 = 药品真实价格 * 药品数量
            BigDecimal medicinePrice = medicineUtil.getRealPrice(medicine.getId()).multiply(BigDecimal.valueOf(simpleMedicineReq.getMedicineNum()));
            // 计算总价
            totalPrice = totalPrice.add(medicinePrice);

            // 收集药品信息
            OrderMedicineInfoResp medicineInfoResp = new OrderMedicineInfoResp();
            medicineInfoResp.setMedicine(medicine);
            medicineInfoResp.setMedicineNum(simpleMedicineReq.getMedicineNum());
            medicineInfoRespList.add(medicineInfoResp);

            // 收集商品描述以供预支付使用
            orderDescription.add(medicine.getCommonNames());
        }

        // 初始化订单
        MmsOrder order = new MmsOrder();
        BeanUtils.copyProperties(orderReq, order);
        order.setUserId(userId);
        order.setIsRefund(OrderConstant.ORDER_IS_REFUND_NO); // 无售后记录
        order.setIsRefunding(false); // 不在售后中
        order.setIsClose(OrderConstant.ORDER_IS_CLOSE_NO); // 没有结束
        order.setIsAbnormal(false); // 订单正常
        order.setMedicineInfo(JSON.toJSONString(medicineInfoRespList)); // 设置药品信息
        // 设置地址信息
        order.setAddressInfo(JSON.toJSONString(addressList.get(0)));
        // 设置订单类型
        if (isNullOrEmpty(orderReq.getType())) {
            order.setType(OrderConstant.ORDER_TYPE_COMMON); // 普通订单
        }
        // 设置订单级别
        if (isNullOrEmpty(orderReq.getType())) {
            order.setOrderLevel(OrderConstant.ORDER_LEVEL_COMMON); // 普通订单
        }

        // 当前时间
        Date nowDate = new Date();
        // 校验优惠券信息
        if (!isNullOrEmpty(orderReq.getUserCouponId())) {
            // 查询当前用户可用优惠券
            List<MmsUserCouponRelationResp> validCouponList = couponUtil.getValidCouponList(userId, totalPrice);
            if (validCouponList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.ORDER_COUPON_NOT_AVAILABLE);
            }

            // 校验优惠券是否可用
            List<MmsUserCouponRelationResp> couponCanUseList = validCouponList.stream().filter(validCoupon ->
                    validCoupon.getId().equals(orderReq.getUserCouponId())).collect(Collectors.toList());
            if (couponCanUseList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.ORDER_COUPON_NOT_AVAILABLE);
            }

            // 使用优惠券
            MmsUserCouponRelationResp couponUsed = couponCanUseList.get(0);
            MmsCouponResp couponInfo = couponUsed.getCouponInfo();
            // 设置 优惠金额
            BigDecimal discountAmount = couponInfo.getDiscountAmount();

            // 校验 总价是否小于优惠价
            if (totalPrice.compareTo(discountAmount) <= 0) {
                discountAmount = totalPrice; // 优惠金额设置为当前总价
                totalPrice = BigDecimal.valueOf(0); // 总价设为0
            } else {
                // 计算总价: 总价 = 总价 - 优惠金额
                totalPrice = totalPrice.subtract(discountAmount);
            }

            // 修改优惠券状态
            MmsUserCouponRelation updUserCoupon = new MmsUserCouponRelation();
            updUserCoupon.setId(couponUsed.getId());
            updUserCoupon.setIsUse(UserCouponRelationConstant.USER_COUPON_RELATION_IS_USE);
            updUserCoupon.setUseTime(nowDate);
            int updNum = mmsUserCouponRelationMapper.updateById(updUserCoupon);
            if (updNum == 0) { // 修改失败
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_GENERATION_FAILED));
            }

            //设置订单优惠券信息
            couponUsed.setDiscountAmount(discountAmount); // 优惠金额
            couponUsed.setIsUse(UserCouponRelationConstant.USER_COUPON_RELATION_IS_USE); // 已使用
            couponUsed.setUseTime(nowDate); // 使用时间
            order.setCouponInfo(JSON.toJSONString(couponUsed));
        }

        // 设置订单总金额
        order.setTotalAmount(totalPrice);

        // 构造回传数据
        MmsOrderResp orderResp = new MmsOrderResp();
        // 总价0元直接设置支付数据
        if (totalPrice.compareTo(BigDecimal.valueOf(0)) == 0) {
            order.setPaymentAmount(BigDecimal.valueOf(0)); // 支付金额
            order.setPaymentMethod(OrderConstant.ORDER_PAYMENT_METHOD_SYSTEM_SKIP); // 支付方式: 系统跳过支付
            order.setPaymentTime(nowDate); // 支付时间
            order.setOrderStatus(OrderConstant.ORDER_STATUS_TO_BE_DELIVERED); // 待发货

            // 保存订单信息
            boolean saveSuccess = this.save(order);
            if (!saveSuccess) { // 保存失败
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_GENERATION_FAILED));
            }
            BeanUtils.copyProperties(order, orderResp);
        } else {
            // 保存订单信息
            order.setOrderStatus(OrderConstant.ORDER_STATUS_TO_BE_PAID); // 待支付
            order.setPaymentMethod(orderReq.getPaymentMethod());
            boolean saveSuccess = this.save(order);
            if (!saveSuccess) { // 保存失败
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_GENERATION_FAILED));
            }

            // 预付款
            PrepayPaymentReq prepayPaymentReq = new PrepayPaymentReq();
            prepayPaymentReq.setDescription(orderDescription.toString()); // 商品描述
            prepayPaymentReq.setOutTradeNo(order.getId()); // 订单号
            prepayPaymentReq.setTimeExpire(TimeUtil.AddDays(nowDate, OrderScheduleConstant.ORDER_SCHEDULE_ORDER_VALIDITY_TIME_DAYS)); // 订单失效时间
            prepayPaymentReq.setPaymentMethod(orderReq.getPaymentMethod());
            // 将总金额转换为分(分后面的四舍五入)
            int total = totalPrice.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).intValue();
            prepayPaymentReq.setTotal(total);
            // 获取预支付id
            String prepayId = paymentUtil.prepayPayment(prepayPaymentReq);
            if (isNullOrEmpty(prepayId)) {
                return CommonResult.failed(CommonCodeEnum.ORDER_PREPAY_FAILED);
            }

            // 保存预支付id
            order.setPrepayId(prepayId);
            boolean updSuccess = this.updateById(order);
            if (!updSuccess) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
            }

            BeanUtils.copyProperties(order, orderResp);

            // 创建订单定时任务
            MmsOrderSchedule orderSchedule = orderScheduleUtil.generateOrderScheduleByType(order.getId(), OrderScheduleConstant.ORDER_SCHEDULE_TYPE_PAYMENT, userId);
            if (orderSchedule == null) {
                return CommonResult.failed(CommonCodeEnum.ORDER_SCHEDULE_GENERATION_FAILED);
            }
            orderResp.setOrderScheduleList(Collections.singletonList(orderSchedule)); // 设置订单定时任务
        }

        orderResp.setMedicineInfo(medicineInfoRespList); // 药品信息
        orderResp.setAddressInfo(addressList.get(0)); // 配送地址信息
        if (order.getCouponInfo() != null) {
            orderResp.setCouponInfo(JSON.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class)); // 优惠信息
        }

        return CommonResult.success(orderResp);
    }

    @Override
    @Transactional
    public ResponseResult payment(MmsOrderReq orderReq, String userId) {
        if (isNullOrEmpty(orderReq.getId(), orderReq.getPaymentMethod())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 校验支付方式
        if (!OrderConstant.PAYMENT_METHOD_LIST.contains(orderReq.getPaymentMethod())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        // 校验订单是否存在
        MmsOrder order = this.getById(orderReq.getId());
        if (order == null) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        // 校验是否本人操作
        if (!Objects.equals(order.getUserId(), userId)) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_OWNER);
        }

        // 记录订单包含药品信息
        List<OrderMedicineInfoResp> medicineInfoRespList = JSON.parseArray(order.getMedicineInfo(), OrderMedicineInfoResp.class);
        // 收集商品描述以供预支付使用
        List<String> orderDescription = new ArrayList<>();
        for (OrderMedicineInfoResp medicineInfoResp : medicineInfoRespList) {
            orderDescription.add(medicineInfoResp.getMedicine().getCommonNames());
        }

        // 设置地址信息
        if (!isNullOrEmpty(orderReq.getAddressId())) {
            List<MmsAddresses> addressList = mmsAddressesMapper.selectList(new LambdaQueryWrapper<MmsAddresses>()
                    .eq(MmsAddresses::getId, orderReq.getAddressId())
                    .eq(MmsAddresses::getUserId, userId));
            if (addressList.isEmpty()) {
                return CommonResult.failed(CommonCodeEnum.ADDRESS_NOT_EXIST);
            }
            order.setAddressInfo(JSON.toJSONString(addressList.get(0)));
        }

        // 设置订单备注
        if (!isNullOrEmpty(orderReq.getNotes())) {
            order.setNotes(orderReq.getNotes());
        }

        // 预付款
        PrepayPaymentReq prepayPaymentReq = new PrepayPaymentReq();
        prepayPaymentReq.setDescription(orderDescription.toString()); // 商品描述
        prepayPaymentReq.setOutTradeNo(order.getId()); // 订单号
        prepayPaymentReq.setTimeExpire(TimeUtil.AddDays(new Date(), OrderScheduleConstant.ORDER_SCHEDULE_ORDER_VALIDITY_TIME_DAYS)); // 订单失效时间
        prepayPaymentReq.setPaymentMethod(orderReq.getPaymentMethod());
        // 将总金额转换为分(分后面的四舍五入)
        int total = order.getTotalAmount().multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).intValue();
        prepayPaymentReq.setTotal(total);
        // 获取预支付id
        String prepayId = paymentUtil.prepayPayment(prepayPaymentReq);
        if (isNullOrEmpty(prepayId)) {
            return CommonResult.failed(CommonCodeEnum.ORDER_PREPAY_FAILED);
        }

        // 保存预支付id
        order.setPrepayId(prepayId);
        order.setPaymentMethod(orderReq.getPaymentMethod());
        boolean updSuccess = this.updateById(order);
        if (!updSuccess) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        // 删除已有的定时任务
        int orderScheduleNum = orderScheduleUtil.getOrderScheduleNum(order.getId(), OrderScheduleConstant.ORDER_SCHEDULE_TYPE_PAYMENT);
        if (orderScheduleNum != -1) {
            if (orderScheduleNum > 0) {
                mmsOrderScheduleMapper.delete(new LambdaQueryWrapper<MmsOrderSchedule>()
                        .eq(MmsOrderSchedule::getOrderId, order.getId()));
            }
        }

        // 创建订单定时任务
        MmsOrderSchedule orderSchedule = orderScheduleUtil.generateOrderScheduleByType(order.getId(), OrderScheduleConstant.ORDER_SCHEDULE_TYPE_PAYMENT, userId);
        if (orderSchedule == null) {
            return CommonResult.failed(CommonCodeEnum.ORDER_SCHEDULE_GENERATION_FAILED);
        }
        // 构造回传数据
        MmsOrderResp orderResp = new MmsOrderResp();
        orderResp.setOrderScheduleList(Collections.singletonList(orderSchedule)); // 设置订单定时任务
        orderResp.setMedicineInfo(medicineInfoRespList); // 药品信息
        orderResp.setAddressInfo(JSON.parseObject(order.getAddressInfo(), MmsAddresses.class)); // 配送地址信息
        if (order.getCouponInfo() != null) {
            orderResp.setCouponInfo(JSON.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class)); // 优惠信息
        }

        return CommonResult.success(orderResp);
    }

    @Override
    @Transactional
    public ResponseResult cancelOrder(MmsOrderReq orderReq, String userId) {
        if (isNullOrEmpty(orderReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        // 校验订单是否存在
        MmsOrder order = this.getById(orderReq.getId());
        if (order == null) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }
        // 订单需为待支付状态
        if (order.getOrderStatus() != OrderConstant.ORDER_STATUS_TO_BE_PAID) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }
        // 订单不可为售后中 且 不可结束
        if (order.getIsRefund() || order.getIsClose()) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }
        // 只可本人操作
        if (!order.getUserId().equals(userId)) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_OWNER);
        }

        // 当前时间
        Date nowDate = new Date();
        // 校验是否超出预支付时间
        List<MmsOrderSchedule> paymentScheduleList = mmsOrderScheduleMapper.selectList(new LambdaQueryWrapper<MmsOrderSchedule>()
                .eq(MmsOrderSchedule::getUserId, userId)
                .eq(MmsOrderSchedule::getOrderId, orderReq.getId())
                .eq(MmsOrderSchedule::getIsClose, false) // 状态未结束
                .eq(MmsOrderSchedule::getType, OrderScheduleConstant.ORDER_SCHEDULE_TYPE_PAYMENT) // 支付进度
                .le(MmsOrderSchedule::getStartTime, nowDate) // 开始时间小于当前时间
                .ge(MmsOrderSchedule::getExpireTime, nowDate)); // 过期时间大于当前时间
        if (paymentScheduleList.size() != 1) {
            return CommonResult.failed(CommonCodeEnum.ORDER_EXCEEDS_PAYMENT_TIME);
        }

        // 修改支付定时任务
        MmsOrderSchedule paymentSchedule = paymentScheduleList.get(0);
        paymentSchedule.setIsClose(true); // 定时任务结束
        paymentSchedule.setEndTime(nowDate); // 结束时间
        paymentSchedule.setUpdateUserId(userId); // 修改人
        int updNum = mmsOrderScheduleMapper.updateById(paymentSchedule);
        if (updNum != 1) { // 修改失败
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_SCHEDULE_UPDATE_FAILED));
        }

        // 修改订单状态
        order.setOrderStatus(OrderConstant.ORDER_STATUS_ORDER_CANCELLED);
        order.setIsClose(OrderConstant.ORDER_IS_CLOSE_YES); // 订单结束
        order.setEndTime(nowDate); // 订单结束时间
        boolean updSuccess = this.updateById(order);
        if (!updSuccess) { // 修改失败
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.ORDER_CANCEL_FAILED));
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult userOrder(Integer pageNum, Integer pageSize, String searchStr, Integer orderStatus, String userId) {
        LambdaQueryWrapper<MmsOrder> queryWrapper = new LambdaQueryWrapper<MmsOrder>()
                .eq(MmsOrder::getUserId, userId)
                .orderByDesc(MmsOrder::getCreateTime);

        if (isNullOrEmpty(searchStr)) {
            StringUtils.deleteWhitespace(searchStr);
            queryWrapper.and(i -> i.like(MmsOrder::getMedicineInfo, searchStr).or() // 药品信息
                    .like(MmsOrder::getAddressInfo, searchStr).or() // 地址信息
                    .like(MmsOrder::getNotes, searchStr)); // 订单备注
        }

        // 订单状态: 0.退款/售后 1.待付款 2.待发货 3.待收货
        if (orderStatus != null) {
            switch (orderStatus) {
                case 0: // 0.退款/售后
                    queryWrapper.eq(MmsOrder::getIsRefund, OrderConstant.ORDER_IS_REFUND_YES);
                    break;
                case OrderConstant.ORDER_STATUS_TO_BE_PAID: // 1.待付款
                case OrderConstant.ORDER_STATUS_TO_BE_DELIVERED: // 2.待发货
                case OrderConstant.ORDER_STATUS_TO_BE_RECEIVED: // 3.待收货
                    queryWrapper.eq(MmsOrder::getOrderStatus, orderStatus)
                            .eq(MmsOrder::getIsRefunding, false); // 不在售后中
                    break;
            }
        }

        // 查询订单
        Page<MmsOrder> page = new Page<>(pageNum, pageSize);
        this.page(page, queryWrapper);

        List<MmsOrderResp> orderRespList = page.getRecords().stream().map(order -> {
            MmsOrderResp orderResp = new MmsOrderResp();
            BeanUtils.copyProperties(order, orderResp);
            orderResp.setMedicineInfo(JSON.parseArray(order.getMedicineInfo(), OrderMedicineInfoResp.class)); // 药品信息
            orderResp.setAddressInfo(JSON.parseObject(order.getAddressInfo(), MmsAddresses.class)); // 配送地址信息
            if (order.getCouponInfo() != null) {
                orderResp.setCouponInfo(JSON.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class)); // 优惠信息
            }

            // 消费积分记录
            if (order.getIsUsePoint()) {
                MmsConsumptionPointRecord pointRecord = mmsConsumptionPointRecordMapper.selectById(order.getPointRecordId());
                if (pointRecord != null) {
                    orderResp.setPointRecord(pointRecord);
                }
            }

            return orderResp;
        }).collect(Collectors.toList());

        return CommonResult.success(orderRespList, (int) page.getTotal());
    }

    @Override
    public ResponseResult orderDetail(String orderId, String userId) {
        MmsOrder order = this.getById(orderId);
        if (isNullOrEmpty(order)) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        MmsOrderResp orderResp = new MmsOrderResp();
        BeanUtils.copyProperties(order, orderResp);
        orderResp.setMedicineInfo(JSON.parseArray(order.getMedicineInfo(), OrderMedicineInfoResp.class)); // 药品信息
        orderResp.setAddressInfo(JSON.parseObject(order.getAddressInfo(), MmsAddresses.class)); // 配送地址信息
        if (order.getCouponInfo() != null) {
            orderResp.setCouponInfo(JSON.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class)); // 优惠信息
        }

        // 设置 退款/售后 信息
        if (order.getIsRefund()) { // 有售后
            List<MmsOrderRefund> orderRefundList = mmsOrderRefundMapper.selectBatchIds(JSON.parseArray(order.getRefundIdList(), String.class));
            if (!orderRefundList.isEmpty()) {
                List<MmsOrderRefundResp> orderRefundRespList = new ArrayList<>();
                for (MmsOrderRefund orderRefund : orderRefundList) {
                    MmsOrderRefundResp orderRefundResp = new MmsOrderRefundResp();
                    BeanUtils.copyProperties(orderRefund, orderRefundResp);

                    orderRefundRespList.add(orderRefundResp);
                }
                orderResp.setRefundInfoList(orderRefundRespList);
            }
        }

        // 消费积分记录
        if (order.getIsUsePoint()) {
            MmsConsumptionPointRecord pointRecord = mmsConsumptionPointRecordMapper.selectById(order.getPointRecordId());
            if (pointRecord != null) {
                orderResp.setPointRecord(pointRecord);
            }
        }

        // 设置定时任务
        List<MmsOrderSchedule> orderScheduleList = orderScheduleUtil.getOrderScheduleList(orderId);
        if (!orderScheduleList.isEmpty()) {
            orderResp.setOrderScheduleList(orderScheduleList);
        }

        return CommonResult.success(orderResp);
    }

    @Override
    @Transactional
    public ResponseResult confirmDeliver(String[] orderId, String userId) {
        List<MmsOrder> orderList = this.listByIds(Arrays.asList(orderId));
        if (orderList.size() != orderId.length) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        for (MmsOrder order : orderList) {
            // 订单非待发货状态不可发货
            if (order.getOrderStatus() != OrderConstant.ORDER_STATUS_TO_BE_DELIVERED) {
                return CommonResult.failed(CommonCodeEnum.ORDER_STATUS_IS_NOT_TO_BE_DELIVERED);
            }
            // 订单已结束
            if (order.getIsClose() == OrderConstant.ORDER_IS_CLOSE_YES) {
                return CommonResult.failed(CommonCodeEnum.ORDER_IS_CLOSED);
            }

            // 关闭发货进度定时任务
            Date nowDate = new Date(); // 当前时间
            List<MmsOrderSchedule> orderScheduleList = orderScheduleUtil.getOrderScheduleList(order.getId());
            if (!orderScheduleList.isEmpty()) {
                // 收集进度表id
                List<String> deliveryScheduleIdList = orderScheduleList.stream().filter(orderSchedule -> {
                    return orderSchedule.getType() == OrderScheduleConstant.ORDER_SCHEDULE_TYPE_DELIVERY;
                }).map(MmsOrderSchedule::getId).distinct().collect(Collectors.toList());
                if (!deliveryScheduleIdList.isEmpty()) {
                    MmsOrderSchedule updOrderSchedule = new MmsOrderSchedule();
                    updOrderSchedule.setIsClose(true);
                    updOrderSchedule.setEndTime(nowDate);
                    updOrderSchedule.setUpdateUserId(userId);
                    int updateNum = mmsOrderScheduleMapper.update(updOrderSchedule, new LambdaQueryWrapper<MmsOrderSchedule>()
                            .in(MmsOrderSchedule::getId, deliveryScheduleIdList));
                    if (updateNum != deliveryScheduleIdList.size()) { // 校验是否修改成功
                        ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
                    }
                }
            }
        }

        // 订单状态改为待收货
        MmsOrder updOrder = new MmsOrder();
        updOrder.setOrderStatus(OrderConstant.ORDER_STATUS_TO_BE_RECEIVED);
        boolean updSuccess = this.update(updOrder, new LambdaQueryWrapper<MmsOrder>()
                .in(MmsOrder::getId, Arrays.asList(orderId)));
        if (!updSuccess) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult takeDelivery(String orderId, String userId) {
        MmsOrder order = this.getById(orderId);
        if (isNullOrEmpty(order)) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }
        // 订单非待收货状态不可收货
        if (order.getOrderStatus() != OrderConstant.ORDER_STATUS_TO_BE_RECEIVED) {
            return CommonResult.failed(CommonCodeEnum.ORDER_STATUS_IS_NOT_TO_BE_RECEIVED);
        }
        // 订单已结束
        if (order.getIsClose() == OrderConstant.ORDER_IS_CLOSE_YES) {
            return CommonResult.failed(CommonCodeEnum.ORDER_IS_CLOSED);
        }

        // 订单状态改为已收货
        order.setOrderStatus(OrderConstant.ORDER_STATUS_ALREADY_RECEIVED);
        boolean updSuccess = this.updateById(order);
        if (!updSuccess) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult getAllOrder(Integer pageNum, Integer pageSize, String searchStr, Integer orderStatus, Integer isClose) {
        LambdaQueryWrapper<MmsOrder> queryWrapper = new LambdaQueryWrapper<MmsOrder>()
                .orderByDesc(MmsOrder::getCreateTime);

        if (!isNullOrEmpty(searchStr)) {
            StringUtils.deleteWhitespace(searchStr);
            queryWrapper.and(i -> i.like(MmsOrder::getMedicineInfo, searchStr).or() // 药品信息
                    .like(MmsOrder::getAddressInfo, searchStr).or() // 地址信息
                    .like(MmsOrder::getNotes, searchStr).or()
                    .like(MmsOrder::getId, searchStr)); // 订单备注
        }

        // 订单状态: 0.退款/售后 1.待付款 2.待发货 3.待收货
        if (orderStatus != null) {
            switch (orderStatus) {
                case 0: // 0.退款/售后
                    queryWrapper.eq(MmsOrder::getIsRefund, OrderConstant.ORDER_IS_REFUND_YES);
                    break;
                case OrderConstant.ORDER_STATUS_TO_BE_PAID: // 1.待付款
                case OrderConstant.ORDER_STATUS_TO_BE_DELIVERED: // 2.待发货
                case OrderConstant.ORDER_STATUS_TO_BE_RECEIVED: // 3.待收货
                    queryWrapper.eq(MmsOrder::getOrderStatus, orderStatus);
                    break;
            }
        }

        // 订单是否结束
        if (isClose != null) {
            if (isClose == 0 || isClose == 1) {
                queryWrapper.eq(MmsOrder::getIsClose, isClose);
            }
        }

        // 查询订单
        Page<MmsOrder> page = new Page<>(pageNum, pageSize);
        this.page(page, queryWrapper);

        List<MmsOrderResp> orderRespList = page.getRecords().stream().map(order -> {
            MmsOrderResp orderResp = new MmsOrderResp();
            BeanUtils.copyProperties(order, orderResp);
            orderResp.setMedicineInfo(JSON.parseArray(order.getMedicineInfo(), OrderMedicineInfoResp.class)); // 药品信息
            orderResp.setAddressInfo(JSON.parseObject(order.getAddressInfo(), MmsAddresses.class)); // 配送地址信息
            if (order.getCouponInfo() != null) {
                orderResp.setCouponInfo(JSON.parseObject(order.getCouponInfo(), MmsUserCouponRelationResp.class)); // 优惠信息
            }

            if (order.getIsRefund()) {
                List<MmsOrderRefund> orderRefundList = mmsOrderRefundMapper.selectList(new LambdaQueryWrapper<MmsOrderRefund>()
                        .eq(MmsOrderRefund::getOrderId, order.getId()));
                List<MmsOrderRefundResp> orderRefundRespList = orderRefundList.stream().map(orderRefund -> {
                    MmsOrderRefundResp orderRefundResp = new MmsOrderRefundResp();
                    BeanUtils.copyProperties(orderRefund, orderRefundResp);

                    MmsUser approver = mmsUserMapper.selectById(orderRefund.getProcessApproverId());
                    if (approver != null) {
                        MmsUserResp userResp = new MmsUserResp();
                        BeanUtils.copyProperties(approver, userResp);
                        orderRefundResp.setApproverInfo(userResp);
                    }

                    return orderRefundResp;
                }).collect(Collectors.toList());
                orderResp.setOrderRefundInfoList(orderRefundRespList);
            }
            return orderResp;
        }).collect(Collectors.toList());

        return CommonResult.success(orderRespList, (int) page.getTotal());
    }
}
